package com.joysuch.wwyt.bp.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.bean.BpHiddenDangerBean;
import com.joysuch.wwyt.bp.bean.BpTaskInvestigateBean;
import com.joysuch.wwyt.bp.bean.TaskListExcelBean;
import com.joysuch.wwyt.bp.bean.investigate.*;
import com.joysuch.wwyt.bp.bean.investigate.vo.TaskListVo;
import com.joysuch.wwyt.bp.bean.investigate.vo.TaskStatiGraphicalVo;
import com.joysuch.wwyt.bp.bean.investigate.vo.TaskVo;
import com.joysuch.wwyt.bp.bean.vo.OldTaskListExcelVo;
import com.joysuch.wwyt.bp.bean.vo.TaskListExcelVo;
import com.joysuch.wwyt.bp.bean.vo.TaskStatiUserExcelVo;
import com.joysuch.wwyt.bp.bean.vo.TaskStatiUserVo;
import com.joysuch.wwyt.bp.constant.InvestigateConfigNames;
import com.joysuch.wwyt.bp.entity.*;
import com.joysuch.wwyt.bp.entity.bean.BpRecordItemBean;
import com.joysuch.wwyt.bp.entity.bean.SimpleInvTaskBean;
import com.joysuch.wwyt.bp.entity.bean.TaskTimeOutWaitingToDo;
import com.joysuch.wwyt.bp.entity.dto.CheckRecordDto;
import com.joysuch.wwyt.bp.entity.dto.UserTaskRecordDto;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigateRecord;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigateRecordItem;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigateTask;
import com.joysuch.wwyt.bp.entity.investigate.BpSafeTableItem;
import com.joysuch.wwyt.bp.entity.vo.AppCheckTaskVo;
import com.joysuch.wwyt.bp.entity.vo.CheckRecordVo;
import com.joysuch.wwyt.bp.enums.RepairStatus;
import com.joysuch.wwyt.bp.enums.SourceType;
import com.joysuch.wwyt.bp.mapper.BpInvestigateTaskHisMapper;
import com.joysuch.wwyt.bp.mapper.BpInvestigateTaskMapper;
import com.joysuch.wwyt.bp.mapper.BpInvestigateTaskSummaryHisMapper;
import com.joysuch.wwyt.bp.mapper.BpInvestigateTaskSummaryMapper;
import com.joysuch.wwyt.bp.repository.BpInvestigateRecordItemDao;
import com.joysuch.wwyt.bp.repository.BpInvestigateRecordRepository;
import com.joysuch.wwyt.bp.repository.BpJobDao;
import com.joysuch.wwyt.bp.repository.BpSafeTableItemDao;
import com.joysuch.wwyt.bp.service.*;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.enums.RiskLevels;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.service.BaseRoleDataAuthService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.risk.entity.vo.RiskMeasureTypeNode;
import com.joysuch.wwyt.risk.service.RiskEvaluationBusinessService;
import com.joysuch.wwyt.risk.service.RiskMeasureTypeService;
import com.joysuch.wwyt.util.FileUtil;
import com.joysuch.wwyt.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author heqifeng
 * @since 2022-04-07
 */
@Service
@Slf4j
public class BpInvestigateTaskServiceImpl extends ServiceImpl<BpInvestigateTaskMapper, BpInvestigateTask> implements BpInvestigateTaskService {

    @Autowired
    private BpInvestigateTaskMapper taskMapper;
    @Autowired
    private BpInvestigateTaskHisMapper taskHisMapper;
    @Autowired
    private BpInvestigateTaskSummaryHisMapper taskSummaryHisMapper;

    @Autowired
    private BaseRoleDataAuthService authService;
    @Autowired
    private BaseUserDao userDao;
    @Autowired
    private BpInvestigateTaskAssignService assignService;
    @Autowired
    private BpInvestigateRecordItemDao recordItemDao;
    @Autowired
    private BpInvestigateRecordRepository recordDao;
    @Autowired
    private BpInvestigateTaskSummaryService taskSummaryService;
    @Autowired
    private BpInvestigateTaskSummaryHisService summaryHisService;
    @Autowired
    private BpInvestigateTaskSummaryService summaryService;
    @Autowired
    private BpInvestigatePlanService planService;
    @Autowired
    private BaseConfigService configService;
    @Autowired
    private InspectExceptionAlarmMesageService inspectExceptionAlarmMesageService;
    @Autowired
    private RiskEvaluationBusinessService riskEvaluationBusinessService;
    @Autowired
    private BpInvestigateTaskHisMapper historyMapper;
    @Autowired
    private BpInvestigateTaskMapper bpInvestigateTaskMapper;
    @Autowired
    private RiskMeasureTypeService riskMeasureTypeService;

    @Resource
    private BpInvestigateConfigService investigateConfigService;

    @Resource
    private BpJobDao jobDao;

    @Autowired
    private BpInvestigateTaskAssignService bpInvestigateTaskAssignService;

    @Autowired
    private BpInvestigateTaskHisMapper bpInvestigateTaskHisMapper;

    @Autowired
    private BpDepartService bpDepartService;

    @Autowired
    private BpSafeTableItemDao tableItemDao;

    @Autowired
    private RedisClient redisClient;

    @Override
    public void batchSave(List<BpInvestigateTask> taskList, Integer batchSize) {
        List<List<BpInvestigateTask>> taskPages = Lists.partition(taskList, batchSize);
        taskPages.forEach(taskPage -> {
            taskMapper.batchInsert(taskPage);
        });
    }

    @Override
    public int batchDown(List<Long> taskIds, String status) {
        if (CollectionUtil.isEmpty(taskIds)) {
            return 0;
        }
        return taskMapper.changeStatusByIds(taskIds, status, new Date());
    }

    @Override
    @Async("investigateTaskTimeCalculate")
    public void sendMassageAndAlarm(List<TaskTimeOutWaitingToDo> waitingNotifyBeans) {
        if (CollectionUtil.isEmpty(waitingNotifyBeans)) {
            return;
        }
        log.info(String.format("waiting notify size: [%s]", waitingNotifyBeans.size()));
        // 个推配置
        boolean needPush = false;
        BaseConfig config = configService.findFirstConfig(BaseConfigCodes.INVESTIGATE_GETUI_ON_OFF);
        needPush = null != config && Constant.COMMON_SWITCH_ON.equals(config.getValue());

        //逾期未排查通知开关
        boolean noCheck = false;
        String noStatus = investigateConfigService.getStatusByName(InvestigateConfigNames.NOTICE_OF_OVERDUE_FAILURE_TO_CHECK);
        noCheck = StringUtils.isNotBlank(noStatus) && Constant.COMMON_SWITCH_ON.equals(noStatus);
        for (TaskTimeOutWaitingToDo each : waitingNotifyBeans) {
            try {
                inspectExceptionAlarmMesageService.saveMessage(each.getPlan().getId(), each.getCheckUserId(), taskMapper.selectById(each.getTaskId()), each.getAlarmContentType(), each.getTenentId(), each.getOrgCode());
            } catch (Exception e) {
                log.error("报警推送异常" , e);
            }
            planService.addUncheckAppNotify(each.getPlan(), each.getTaskId(), needPush, noCheck);
        }
    }

    @Override
    public BpInvestigateTask findByPlanId(Long planId) {
        return taskMapper.findByPlanId(planId);
    }

    @Override
    public Page<BpTaskInvestigateBean> getTroubleshootingStatistics(TaskSearchBean search) {
        search.setTenentId(Context.getCurrentTenantId());
        search.setOrgCode(Context.getCurrentOrgCode());
        Page<TaskStatiUserVo> page = new Page<>(search.getPage() + 1, search.getSize());
        Page<BpTaskInvestigateBean> resultPage = taskMapper.getTroubleshootingStatistics(page, search);
        for (BpTaskInvestigateBean record : resultPage.getRecords()) {
            double finishProbability=0d;
            if (record!=null&&record.getTotalTask()!=0) {
                finishProbability =(double)(record.getTotalTask() - record.getUnCheckTask()) / record.getTotalTask()*100;
                String finishProbabilityStr = String.format("%.2f", finishProbability);
                finishProbability=  Double.parseDouble(finishProbabilityStr);
            }
            record.setFinishProbability(finishProbability);
        }
        return resultPage;
    }

    @Override
    public BpTaskInvestigateBean getBpTaskInvestigateBean(TaskSearchBean search) {
        search.setTenentId(Context.getCurrentTenantId());
        search.setOrgCode(Context.getCurrentOrgCode());
        BpTaskInvestigateBean record = taskMapper.getBpTaskInvestigateBean(search);
//        record.setNoCheckTask(record.getTotalTask()-record.getFinishTask()-record.getUnCheckTask());
        double finishProbability=0d;
        if (record!=null&&record.getTotalTask()!=0) {
            finishProbability =(double)(record.getTotalTask() - record.getUnCheckTask()) / record.getTotalTask()*100;
            String finishProbabilityStr = String.format("%.2f", finishProbability);
            finishProbability=  Double.parseDouble(finishProbabilityStr);
        }
        record.setFinishProbability(finishProbability);
        return record;
    }

    @Override
    public Page<BpHiddenDangerBean> getBpHiddenDangerBeanStatistics(TaskSearchBean search) {
        search.setTenentId(Context.getCurrentTenantId());
        search.setOrgCode(Context.getCurrentOrgCode());
        Page<TaskStatiUserVo> page = new Page<>(search.getPage() + 1, search.getSize());
        Map<String,String> map = getConfig();
        List<String> states = getStates();
        Page<BpHiddenDangerBean> hiddenDangerBeanPage = taskMapper.getBpHiddenDangerBeanStatistics(page, search, map.get("bizName"),
                map.get("dateName"),  map.get("departName"),map.get("reportTime"),map.get("verificationName"),states);
        for (BpHiddenDangerBean record : hiddenDangerBeanPage.getRecords()) {
            double finishProbability=0d;
            if (record!=null&&record.getTotalHidden()!=0) {
                finishProbability =(double) (record.getTotalHidden() - record.getOverdueHiddenNum()) / record.getTotalHidden()*100;
                String finishProbabilityStr = String.format("%.2f", finishProbability);
                finishProbability=  Double.parseDouble(finishProbabilityStr);
            }
            record.setFinishProbability(finishProbability);
        }
        return hiddenDangerBeanPage;
    }

    public Map<String,String> getConfig(){
        Map<String,String> map=new HashMap();
        map.put("bizName","隐患管理");

        map.put("reportTime","上报时间");
        map.put("departName","责任单位");
        map.put("dateName","要求完成日期");
        map.put("verificationName","验证日期");
        map.put("reportUser","上报人员");
        BaseConfig config = configService.findConfig(BaseConfigCodes.WORKFLOW_FIELD);
        BaseConfig processConfig = configService.findConfig(BaseConfigCodes.WORKFLOW_PROCESS_NAME);
        if (config!=null&&StringUtils.isNotBlank(config.getValue())){
            String[] split = config.getValue().split(",");
            if (split[0]!=null) {
                map.put("reportTime",split[0]);
            }
            if (split[1]!=null) {
                map.put("departName",split[1]);
            }

            if (split[2]!=null) {
                map.put("dateName",split[2]);
            }
            if (split[3]!=null) {
                map.put("verificationName",split[3]);
            }
            if (split[4]!=null) {
                map.put("reportUser",split[4]);
            }
        }
        if (processConfig!=null&&StringUtils.isNotBlank(processConfig.getValue())){
            String[] split = processConfig.getValue().split(",");
            if (split[0]!=null) {
                map.put("bizName",split[0]);
            }
        }
        return map;
    }

    public List<String> getStates(){
        ArrayList<String> list = Lists.newArrayList("整改中", "立即整改中","整改验收中");
        BaseConfig stateConfig = configService.findConfig(BaseConfigCodes.WORKFLOW_STATE_FIELD);
        if (stateConfig!=null&& StringUtils.isNotBlank(stateConfig.getValue())) {
            String[] split = stateConfig.getValue().split(",");
            if (split!=null&&split.length>0) {
                list.clear();
                for (String s : split) {
                    list.add(s);
                }
            }
        }
        return list;
    }

    @Override
    public BpHiddenDangerBean getBpHiddenDangerBean(TaskSearchBean search) {
        search.setTenentId(Context.getCurrentTenantId());
        search.setOrgCode(Context.getCurrentOrgCode());
        Map<String,String> map = getConfig();
        List<String> states = getStates();
        BpHiddenDangerBean record = taskMapper.getBpHiddenDangerBean(search,  map.get("bizName"),
                map.get("dateName"),  map.get("departName"),map.get("reportTime"),map.get("verificationName"),states);
        double finishProbability=0.0d;
        if (record!=null&&record.getTotalHidden()!=0) {
            finishProbability =(double) (record.getTotalHidden() - record.getOverdueHiddenNum()) / record.getTotalHidden()*100;
            String finishProbabilityStr = String.format("%.2f", finishProbability);
            finishProbability=  Double.parseDouble(finishProbabilityStr);
        }
        record.setFinishProbability(finishProbability);
        return record;
    }

    @Override
    public void affectRiskLever(List<BpInvestigateRecordItem> recordItems, Map<Long, Long> recordPlanMapping) {
        List<BpRecordItemBean> uncheckedBeanList = new ArrayList<>();
        recordItems.forEach(item -> {
            uncheckedBeanList.add(new BpRecordItemBean(item.getId(), recordPlanMapping.get(item.getRecordId())));
        });
        if (!CollectionUtils.isEmpty(uncheckedBeanList)) {
            //未检
            riskEvaluationBusinessService.convertUnCheckedRealRiskLevel(uncheckedBeanList);
        }
    }

    @Override
    public List<SimpleInvTaskBean> findDeadTask(Date currDate) {
        if (null == currDate) {
            return null;
        }
        return taskMapper.selectByDeadLine(currDate);
    }

    @Override
    public List<SimpleInvTaskBean> findCloseTask(Date currDate) {
        if (null == currDate) {
            return null;
        }
        return taskMapper.selectByCheckDate(currDate);
    }

    @Override
    public Page<TaskListVo> getTaskRecordHistoryList(TaskSearchBean search) {
        search.setOrgCode(Context.getCompanyCode());
        search.setTenentId(Context.getCurrentTenantId());
        search.setEndTime(search.getEndTime() != null ? DateUtil.endOfDay(search.getEndTime()) : null);
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 按人员搜索，查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                return new Page<>();
            }
            search.setCheckUserIds(userIds);
        }
        List<Long> currAuthDepartIds = authService.findDepartIdsByCurUser();
        // 无数据权限，直接返回
        if (CollectionUtil.isEmpty(currAuthDepartIds)) {
            return new Page<>();
        }
        search.setAuthDepartIds(currAuthDepartIds);
        Page<BpInvestigateTask> page = new Page<>(search.getPage() + 1, search.getSize());
        page.setSearchCount(false);
        Page<TaskListVo> taskPage = taskMapper.selectHistoryTaskPage(page, search);

        Long count = taskMapper.selectHistoryTaskCount(search);
        taskPage.setTotal(count);

        if (!CollectionUtils.isEmpty(taskPage.getRecords())) {
            convert(taskPage.getRecords());
        }
        return taskPage;
    }

    @Override
    public Page<TaskListVo> getTaskRecordTodayList(TaskSearchBean search) {
        search.setOrgCode(Context.getCompanyCode());
        search.setTenentId(Context.getCurrentTenantId());
        search.setEndTime(search.getEndTime() != null ? DateUtil.endOfDay(search.getEndTime()) : null);
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 按人员搜索，查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                return new Page<>();
            }
            search.setCheckUserIds(userIds);
        }
        List<Long> currAuthDepartIds = authService.findDepartIdsByCurUser();
        // 无数据权限，直接返回
        if (CollectionUtil.isEmpty(currAuthDepartIds)) {
            return new Page<>();
        }
        search.setAuthDepartIds(currAuthDepartIds);

        Page<BpInvestigateTask> page = new Page<>(search.getPage() + 1, search.getSize());
        page.setSearchCount(false);
        Page<TaskListVo> taskPage = taskMapper.selectTodayTaskPage(page, search);

        Long count = taskMapper.selectTodayTaskCount(search);
        taskPage.setTotal(count);

        if (!CollectionUtils.isEmpty(taskPage.getRecords())) {
            convert(taskPage.getRecords());
        }
        return taskPage;
    }

    @Override
    public Page<TaskListVo> getTaskRecordHistoryNewList(TaskSearchBean search) {
        search.setOrgCode(Context.getCompanyCode());
        search.setTenentId(Context.getCurrentTenantId());
        search.setEndTime(search.getEndTime() != null ? DateUtil.endOfDay(search.getEndTime()) : null);
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 按人员搜索，查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                return new Page<>();
            }
            search.setCheckUserIds(userIds);
        }
        List<Long> currAuthDepartIds = authService.findDepartIdsByCurUser();
        // 无数据权限，直接返回
        if (CollectionUtil.isEmpty(currAuthDepartIds)) {
            return new Page<>();
        }
        search.setAuthDepartIds(currAuthDepartIds);
        Page<BpInvestigateTask> page = new Page<>(search.getPage() + 1, search.getSize());
        page.setSearchCount(false);
        Page<TaskListVo> taskPage = taskMapper.selectHistoryNewTaskPage(page, search);
        Long count = taskMapper.selectHistoryNewTaskCount(search);
        taskPage.setTotal(count);
        if (!CollectionUtils.isEmpty(taskPage.getRecords())) {
            convert(taskPage.getRecords());
        }
        return taskPage;
    }


    @Override
    public List<TaskListExcelBean> getTaskRecords(TaskSearchBean search) {
        List<TaskListExcelBean> list = new ArrayList<>();
        search.setOrgCode(Context.getCompanyCode());
        search.setTenentId(Context.getCurrentTenantId());
        search.setEndTime(search.getEndTime() != null ? DateUtil.endOfDay(search.getEndTime()) : null);
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 按人员搜索，查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                return list;
            }
            search.setCheckUserIds(userIds);
        }
        List<Long> currAuthDepartIds = authService.findDepartIdsByCurUser();
        // 无数据权限，直接返回
        if (CollectionUtil.isEmpty(currAuthDepartIds)) {
            return list;
        }
        search.setAuthDepartIds(currAuthDepartIds);
        Page<BpInvestigateTask> page = new Page<>(search.getPage() + 1, search.getSize());
        page.setSearchCount(false);
        list = taskMapper.selectHistorys(page, search);
        return list;
    }

    @Override
    public Long getTaskRecordCountAll() {
        String orgCode = Context.getCompanyCode();
        Long tenantId = Context.getCurrentTenantId();
        List<Long> currAuthDepartIds = authService.findDepartIdsByCurUser();
        // 无数据权限，直接返回
        if (CollectionUtil.isEmpty(currAuthDepartIds)) {
            return 0L;
        }
        Long count = taskMapper.selectTaskRecordCountAll(tenantId, orgCode, currAuthDepartIds);
        return count;
    }

    public CheckRecordVo getRecordDetail(Long taskId) {
        // task表不存在此id，则后续从task_his表里查
        boolean isHistory = !taskId.equals(taskMapper.exitsId(taskId));
        CheckRecordDto recordDto = taskMapper.selectRecordDetail(taskId, isHistory);
        List<CheckRecordDto> dtos = Arrays.asList(recordDto);
        taskSummaryService.uncheckConvert(dtos);
        List<CheckRecordVo> recordVos = taskSummaryService.convertDtoToVoBatch(dtos, isHistory);
        return recordVos.get(0);
    }


    public List<TaskListExcelBean> getNewRecordDetail(List<Long> taskIds) {
        List<TaskListExcelBean> list = new ArrayList<>();
        // task表不存在此id，则后续从task_his表里查
        List<Long> trueIds = new ArrayList<>();
        List<Long> falseIds = new ArrayList<>();
//        falseIds = taskMapper.exitsIds(taskIds);
//        taskIds.removeAll(falseIds);
//        trueIds=taskIds;
        Map<String, List<Long>> map = getTaskIds(taskIds);
        trueIds = map.get("trueIds");
        falseIds = map.get("falseIds");
        List<SimpleTaskAssign> simpleAssign = new ArrayList<>();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(trueIds)) {
            List<TaskListExcelBean> tDtos = getBean(trueIds, true);
            list.addAll(tDtos);
        }
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(falseIds)) {
            List<TaskListExcelBean> fDtos = getBean(falseIds, false);
            list.addAll(fDtos);
        }
        Map<Long, List<SimpleTaskAssign>> taskAssignMapping = simpleAssign.stream().collect(Collectors.groupingBy(SimpleTaskAssign::getTaskId));

        List<TaskListExcelBean> beanList = list.stream().distinct().collect(Collectors.toList());
        beanList.forEach(taskListExcelBean -> {
            taskListExcelBean.setSimpleAssign(taskAssignMapping.get(taskListExcelBean.getId()));
        });
        return beanList;
    }

    public Map<String, List<Long>> getTaskIds(List<Long> taskIds) {
        Map<String, List<Long>> map = new HashMap<>();
        if (taskIds.size() >= 500) {
            int last = taskIds.size() / 500;
            int remainder = taskIds.size() % 500;
            if (remainder != 0) {
                last++;
            }
            for (int i = 0; i < last; i++) {
                List<Long> idList = new ArrayList<>();
                if (last == i + 1) {
                    idList = taskIds.subList(i * 500, taskIds.size());
                } else {
                    idList = taskIds.subList(i * 500, (i + 1) * 500);
                }
                List<Long> falseIds = taskMapper.exitsIds(idList);
                idList.removeAll(falseIds);
                List<Long> falseIdList = map.get("falseIds");
                List<Long> trueIdList = map.get("trueIds");
                if (CollectionUtils.isEmpty(falseIdList)) {
                    falseIdList = new ArrayList<>();
                }
                if (CollectionUtils.isEmpty(trueIdList)) {
                    trueIdList = new ArrayList<>();
                }
                if (!CollectionUtils.isEmpty(falseIds)) {
                    falseIdList.addAll(falseIds);
                }
                if (!CollectionUtils.isEmpty(idList)) {
                    trueIdList.addAll(idList);
                }
                map.put("falseIds", falseIdList);
                map.put("trueIds", trueIdList);
            }
        } else {
            List<Long> falseIds = taskMapper.exitsIds(taskIds);
            taskIds.removeAll(falseIds);
            map.put("falseIds", falseIds);
            map.put("trueIds", taskIds);
        }
        return map;
    }

    public List<TaskListExcelBean> getBean(List<Long> ids, boolean isHistory) {
        List<TaskListExcelBean> list = new ArrayList<>();
        if (ids.size() >= 1000) {
            int last = ids.size() / 1000;
            int remainder = ids.size() % 1000;
            if (remainder != 0) {
                last++;
            }
            for (int i = 0; i < last; i++) {
                List<Long> idList;
                if (last == i + 1) {
                    idList = ids.subList(i * 1000, ids.size());
                } else {
                    idList = ids.subList(i * 1000, (i + 1) * 1000);
                }
                List<TaskListExcelBean> beans = taskMapper.selectCheckRecordDetail(idList, isHistory);

                list.addAll(beans);
            }
        } else {
            list = taskMapper.selectCheckRecordDetail(ids, isHistory);
        }
        return list;
    }


    private void convert(List<TaskListVo> records) {
        Map<Long,List<Long>> noCheckUserMap=new HashMap<>();
        for (TaskListVo record : records) {
            //查找未检人员为-1的
            if (record!=null&&record.getCheckUser()!=null&&record.getCheckUser()==-1){
                List<Long> userIds = noCheckUserMap.get(record.getId());
                if (CollectionUtils.isEmpty(userIds)) {
                    userIds  = taskMapper.findUserIds(record.getId());
                }
                if (!CollectionUtils.isEmpty(userIds)) {
                    record.setCheckUser(CollectionUtils.isEmpty(userIds)?-1:userIds.get(0));
                    userIds.remove(0);
                    noCheckUserMap.put(record.getId(),userIds);
                }
            }
        }

        // 正常完成的任务
        List<Long> checkUserIds = records.stream().filter(each -> each.getCheckUser() != null && each.getCheckUser() != -1).map(TaskListVo::getCheckUser).collect(Collectors.toList());
        List<BaseUser> checkUsers = CollectionUtil.isEmpty(checkUserIds) ? new ArrayList<>() : userDao.getAllByIds(checkUserIds);
        Map<Long, BaseUser> checkUserMapping = checkUsers.stream().collect(Collectors.toMap(BaseUser::getId, r -> r));

        // 旧隐患排查的检查人
        List<Long> taskUserId = records.stream().filter(each -> each.getTaskUserId() != null).map(TaskListVo::getTaskUserId).collect(Collectors.toList());
        List<BaseUser> taskUsers = CollectionUtil.isEmpty(taskUserId) ? new ArrayList<>() : userDao.getAllByIds(taskUserId);
        Map<Long, BaseUser> taskUserMapping = taskUsers.stream().collect(Collectors.toMap(BaseUser::getId, r -> r));

        // 异常处理结果（用于计算旧任务的异常处理状态）
        List<Long> allTaskIds = records.stream().map(TaskListVo::getId).collect(Collectors.toList());
        List<SimpleRecordItem> excepHandles = CollectionUtil.isEmpty(allTaskIds) ? new ArrayList<>() : taskMapper.selectSimpleItem(allTaskIds);
        Map<Long, List<SimpleRecordItem>> simpleRecordMapping = excepHandles.stream().collect(Collectors.groupingBy(SimpleRecordItem::getTaskId));

        List<Long> planIds = records.stream().map(TaskListVo::getPlanId).collect(Collectors.toList());
        List<Long> planUsers = new ArrayList<>();

        List<BaseUser> planUserList = CollectionUtil.isEmpty(planUsers) ? new ArrayList<>() : userDao.getAllByIds(planUsers);
        records.forEach(each -> {
            // 新老数据的异常处理结果区别对待,
            if (SourceType.NEW.getValue().equals(each.getSourceType())) {
                if (null != each.getCheckUser() && each.getCheckUser() != -1) {
                    BaseUser checkUser = checkUserMapping.get(each.getCheckUser());
                    if (checkUser != null) {
                        each.setCheckUserNames(checkUser.getRealName());
                    }
                }
                // 新隐患排查一个task只会有一个异常处理状态
                SimpleRecordItem simpleRecordItem = null;
                List<SimpleRecordItem> items = simpleRecordMapping.get(each.getId());
                if (CollectionUtil.isNotEmpty(items)) {
                    simpleRecordItem = simpleRecordMapping.get(each.getId()).get(0);
                }
                if (simpleRecordItem != null) {
                    String status = simpleRecordItem.getRepairStatus();
                    each.setExceptStatus(calculateExceptionHandleStatus4New(status));
                    each.setRecordItemId(simpleRecordItem.getItemId());
                    each.setWokeFlowId(simpleRecordItem.getWorkFlowId());
                }
            } else if (SourceType.OLD.getValue().equals(each.getSourceType())) {
                // 老数据只计算出异常处理状态和任务分配人，不设置itemId
                String status = calculateExceptionHandleStatus4Old(simpleRecordMapping.get(each.getId()));
                each.setExceptStatus(status);
                if (each.getTaskUserId() != null) {
                    each.setCheckUserNames(taskUserMapping.get(each.getTaskUserId()).getRealName());
                }
            }

        });
    }

    private String calculateExceptionHandleStatus4Old(List<SimpleRecordItem> simpleRecordItems) {
        String result = "无需处理";
        if (CollectionUtil.isEmpty(simpleRecordItems)) {
            return result;
        }
        List<String> repairStatus = simpleRecordItems.stream().map(SimpleRecordItem::getRepairStatus).collect(Collectors.toList());
        // 存在未整改
        if (repairStatus.contains("未整改")) {
            result = "等待处理";
        } else if (repairStatus.contains("已处理")) {
            result = "已处理";
        }
        return result;
    }

    private String calculateExceptionHandleStatus4New(String status) {
        String result = "无需处理";
        if (StringUtils.isBlank(status)) {
            return result;
        }
        if (status.equals("未整改")) {
            result = "等待处理";
        } else if (status.equals("已处理")) {
            result = "已处理";
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRecord(Long id) {
        // task表中不存在此ID，表示该条数据为历史数据
        boolean isHistory = !id.equals(taskMapper.exitsId(id));
        BpInvestigateTask task;
        BpInvestigateRecord record;
        boolean result;
        if (isHistory) {
            // 从历史表里删
            task = historyMapper.getHistoryTaskById(id);
            if (null == task) {
                return false;
            }
            record = historyMapper.getRecordByTaskId(id,Boolean.TRUE);
            result = historyMapper.deleteTaskById(id);
        } else {
            // 从今日表里删
            task = getById(id);
            if (null == task) {
                return false;
            }
            record = recordDao.findFirstByTaskIdAndSourceType(id, SourceType.NEW.getValue());
//            result = saveOrUpdate(task);
            result = bpInvestigateTaskMapper.deleteTaskById(id);
        }
        // 删除任务后，更新summary中的计数
        List<Long> users = historyMapper.getAssignUserByTaskId(id, isHistory);
        // 区分新老隐患排查，新数据更新各类计数，老数据直接删除
        if (SourceType.NEW.getValue().equals(task.getSourceType())) {
            // 根据检查结果、任务分配人、任务时间 更新历史汇总的各种计数情况
            historyMapper.updateSummaryCountByUserAndDate(users, DateUtil.beginOfDay(task.getCheckDate()), record.getCheckResult(), isHistory);
            // 任务删除后，对应的汇总完成、异常处理等状态处理
            updateSummaryState4DeleteTask(task,isHistory);
        } else {
            // 旧隐患排查，summary与task一对一，直接删除
            historyMapper.deleteSummaryByTaskId(id, isHistory);
        }
        return result;
    }

    private void updateSummaryState4DeleteTask(BpInvestigateTask task, boolean isHistory) {
        BpInvestigateRecord record = historyMapper.getRecordByTaskId(task.getId(),isHistory);
        Date taskCheckDate = record.getCheckFinishDate();
        List<BpInvestigateTaskSummaryHis> summaryHis = historyMapper.getSummaryByTaskId(task.getId(), DateUtil.beginOfDay(taskCheckDate),isHistory);
        if (CollectionUtil.isNotEmpty(summaryHis)) {
            Date startTime = DateUtil.beginOfDay(taskCheckDate);
            DateTime endTime = DateUtil.beginOfDay(DateUtil.offsetDay(taskCheckDate, 1));
            List<Long> userIds = summaryHis.stream().map(BpInvestigateTaskSummaryHis::getUserId).collect(Collectors.toList());
            // 全部查询后 按用户id分组，避免循环体中查库
            List<UserTaskRecordDto> repairStatus = historyMapper.findRepairStatusByDate(startTime, endTime, userIds,isHistory);
            Map<Long, List<UserTaskRecordDto>> repairStatusGroup = CollectionUtil.isNotEmpty(repairStatus) ?
                    repairStatus.stream().collect(Collectors.groupingBy(UserTaskRecordDto::getCheckUserId)) : new HashMap<>();

            summaryHis.forEach(each -> {
                List<UserTaskRecordDto> currentRepairStatus = repairStatusGroup.get(each.getUserId());
                if (CollectionUtils.isEmpty(currentRepairStatus)) {
                    each.setExceptionProcessResult(RepairStatus.NO_PROCESSING_REQUIRED.getDesc());
                } else {
                    List<String> exceptionProcessList = currentRepairStatus.stream().map(UserTaskRecordDto::getRepairStatus)
                            .filter(ex -> org.apache.commons.lang3.StringUtils.isNotBlank(ex) && !RepairStatus.NO_RECTIFICATION_REQUIRED.getDesc().equals(ex)).collect(Collectors.toList());
                    each.setExceptionProcessResult(calculateExceptionHandleStatus4Delete(exceptionProcessList));
                }
            });
            if (isHistory){
                summaryHisService.updateBatchById(summaryHis);
            }else {
                if (!CollectionUtils.isEmpty(summaryHis)){
                    List<BpInvestigateTaskSummary> collect = summaryHis.stream().map(bpInvestigateTaskSummaryHis -> {
                        BpInvestigateTaskSummary bpInvestigateTaskSummary = new BpInvestigateTaskSummary();
                        BeanUtils.copyProperties(bpInvestigateTaskSummaryHis, bpInvestigateTaskSummary);
                        return bpInvestigateTaskSummary;
                    }).collect(Collectors.toList());
                    summaryService.updateBatchById(collect);
                }
            }
        }
    }


//    private void updateSummaryState4DeleteTask(BpInvestigateTask task) {
//        BpInvestigateRecord record = historyMapper.getRecordByTaskId(task.getId());
//        Date taskCheckDate = record.getCheckFinishDate();
//        List<BpInvestigateTaskSummaryHis> summaryHis = historyMapper.getSummaryByTaskId(task.getId(), DateUtil.beginOfDay(taskCheckDate));
//        if (CollectionUtil.isNotEmpty(summaryHis)) {
//            Date startTime = DateUtil.beginOfDay(taskCheckDate);
//            DateTime endTime = DateUtil.beginOfDay(DateUtil.offsetDay(taskCheckDate, 1));
//            List<Long> userIds = summaryHis.stream().map(BpInvestigateTaskSummaryHis::getUserId).collect(Collectors.toList());
//            // 全部查询后 按用户id分组，避免循环体中查库
//            List<UserTaskRecordDto> repairStatus = historyMapper.findRepairStatusByDate(startTime, endTime, userIds);
//            Map<Long, List<UserTaskRecordDto>> repairStatusGroup = CollectionUtil.isNotEmpty(repairStatus) ?
//                    repairStatus.stream().collect(Collectors.groupingBy(UserTaskRecordDto::getCheckUserId)) : new HashMap<>();
//
//            summaryHis.forEach(each -> {
//                List<UserTaskRecordDto> currentRepairStatus = repairStatusGroup.get(each.getUserId());
//                if (CollectionUtils.isEmpty(currentRepairStatus)) {
//                    each.setExceptionProcessResult(RepairStatus.NO_PROCESSING_REQUIRED.getDesc());
//                } else {
//                    List<String> exceptionProcessList = currentRepairStatus.stream().map(UserTaskRecordDto::getRepairStatus)
//                            .filter(ex -> org.apache.commons.lang3.StringUtils.isNotBlank(ex) && !RepairStatus.NO_RECTIFICATION_REQUIRED.getDesc().equals(ex)).collect(Collectors.toList());
//                    each.setExceptionProcessResult(calculateExceptionHandleStatus4Delete(exceptionProcessList));
//                }
//            });
//            summaryHisService.updateBatchById(summaryHis);
//        }
//    }

    String calculateExceptionHandleStatus4Delete(List<String> exceptionProcessList) {
        if (CollectionUtil.isEmpty(exceptionProcessList)) {
            return RepairStatus.NO_PROCESSING_REQUIRED.getDesc();
        }
        List<String> repairStatus = exceptionProcessList.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(repairStatus)) {
            // 存在未整改，返回等待处理
            if (repairStatus.contains(RepairStatus.NOT_RECTIFIED.getDesc())) {
                return RepairStatus.WAITING_FOR_PROCESSING.getDesc();
            } else if (repairStatus.contains(RepairStatus.PROCESSED.getDesc())) {
                // 不存在未整改，存在已处理，返回已处理
                return RepairStatus.PROCESSED.getDesc();
            }
        }
        return RepairStatus.NO_PROCESSING_REQUIRED.getDesc();
    }

    @Override
    public Page<TaskStatiUserVo> getStatistics(TaskSearchBean search) {
        search.setTenentId(Context.getCurrentTenantId());
        search.setOrgCode(Context.getCurrentOrgCode());
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                return new Page<>();
            }
            search.setCheckUserIds(userIds);

        }
        Page<TaskStatiUserVo> page = new Page<>(search.getPage() + 1, search.getSize());
        Page<TaskStatiUserVo> userDetail = taskMapper.getDetailGroupByUser(page, search);
        if (CollectionUtil.isNotEmpty(userDetail.getRecords())) {
            List<TaskStatiUserVo> list = userDetail.getRecords();
//            List<Long> userIds = list.stream().map(TaskStatiUserVo::getUserId).collect(Collectors.toList());
//            search.setCheckUserIds(userIds);
            HdFieldConfigBean hdFieldConfig = buildHdFieldConfig();
            List<TaskStatiUserVo> taskList = taskMapper.getTaskDetailGroupByUser(search, hdFieldConfig);
            Map<Long, TaskStatiUserVo> totalHiddenMap = taskList.stream().collect(Collectors.toMap(TaskStatiUserVo::getUserId, t -> t));
            for (TaskStatiUserVo vo : list) {
                TaskStatiUserVo userVo = totalHiddenMap.get(vo.getUserId());
                if (userVo != null) {
                    vo.setTotalHidden(userVo.getTotalHidden());
                }
            }

        }

//        for (TaskStatiUserVo record : userDetail.getRecords()) {
//            record.setNoCheckTask(record.getTotalTask()-record.getFinishTask()-record.getUnCheckTask()-record.getTimeOutFinish());
//        }
        return userDetail;
    }

    /**
     * 隐患治理流程名称及字段配置
     * @return
     */
    private HdFieldConfigBean buildHdFieldConfig() {
        Map<String, String> configMap = getConfig();
        HdFieldConfigBean fieldConfig = new HdFieldConfigBean();
        // 流程名称
        fieldConfig.setBizName(configMap.get("bizName"));
        // 要求完成日期
        fieldConfig.setDateName(configMap.get("dateName"));
        // 责任单位
        fieldConfig.setDepartName(configMap.get("departName"));
        // 上报时间
        fieldConfig.setReportTime(configMap.get("reportTime"));
        // 上报人员
        fieldConfig.setReportUser(configMap.get("reportUser"));
        // 验证日期
        fieldConfig.setVerificationName(configMap.get("verificationName"));
        return fieldConfig;
    }

    @Override
    public TaskStatiGraphicalVo getStatisticsGraphical(TaskSearchBean search) {
        search.setOrgCode(Context.getCurrentOrgCode());
        search.setTenentId(Context.getCurrentTenantId());

        TaskStatiGraphicalVo graphicalVo = new TaskStatiGraphicalVo();
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                graphicalVo.setFinishTask(0).setTimeOutFinish(0).setTotalHidden(0).setUnCheckTask(0).setTotalTask(0);
                return graphicalVo;
            }
            search.setCheckUserIds(userIds);

        }
        TaskStatiUserVo graphicalMeta = taskMapper.getAllGraphical(search);
        HdFieldConfigBean hdFieldConfig = buildHdFieldConfig();
        TaskStatiUserVo graphicalTask = taskMapper.getTaskGraphical(search, hdFieldConfig);
        if (graphicalTask != null && graphicalMeta != null){
            graphicalMeta.setTotalHidden(graphicalTask.getTotalHidden());
        }

        if (graphicalMeta == null) {
            graphicalVo.setFinishTask(0).setTimeOutFinish(0).setTotalHidden(0).setUnCheckTask(0).setTotalTask(0);
            return graphicalVo;
        }

        BeanUtils.copyProperties(graphicalMeta, graphicalVo);

        int totalTask = graphicalMeta.getTotalTask() == null ? 0 : graphicalMeta.getTotalTask();
        int finishTask = graphicalMeta.getFinishTask() == null ? 0 : graphicalMeta.getFinishTask();
        int timeOutFinish = graphicalMeta.getTimeOutFinish() == null ? 0 : graphicalMeta.getTimeOutFinish();

        double taskFinishRatio = totalTask == 0 ? 0 : (double) finishTask / (double) totalTask;
        double timeOutFinishRatio = totalTask == 0 ? 0 : (double) timeOutFinish / (double) totalTask;

        graphicalVo.setTaskFinishRatio(taskFinishRatio);
        graphicalVo.setTimeOutFinishRatio(timeOutFinishRatio);
//        graphicalVo.setNoCheckTask(totalTask-finishTask-graphicalVo.getUnCheckTask()-graphicalVo.getTimeOutFinish());
        return graphicalVo;
    }

    @Override
/*    public void exportReport(TaskSearchBean search, HttpServletRequest request, HttpServletResponse
            response) throws IOException {
        setPageParam(search);
        Page<TaskListVo> recordPage = getTaskRecordHistoryList(search);
        List<TaskListVo> records = recordPage.getRecords();
        ArrayList<TaskListExcelBean> exportBeans = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(records)) {
            records.forEach(each -> {
                TaskListExcelBean exportBean = new TaskListExcelBean();
                BeanUtils.copyProperties(each,exportBean);
                exportBeans.add(exportBean);
            });
        }
        OutputStream planStatOut = response.getOutputStream();
        ExcelWriter planStatWriter = ExcelUtil.getWriter(true);
        buildRecordExcelHeader(planStatWriter);
        planStatWriter.write(exportBeans, true);
        String planFileName = FileUtil.getEncodeFileName(request, "隐患排查记录");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", String.format("attachment;filename=%s", planFileName + ".xlsx"));
        planStatWriter.flush(planStatOut, true);
        planStatWriter.close();
        IoUtil.close(planStatOut);
        }*/


    public void exportReport(TaskSearchBean search, HttpServletRequest request, HttpServletResponse
            response) throws IOException {
        setPageParam(search);
//        Page<TaskListVo> recordPage = getTaskRecordHistoryList(search);
        List<TaskListExcelBean> list = getTaskRecords(search);
        List<TaskListExcelVo> vos = new ArrayList<>();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)) {
            List<Long> ids = list.stream().map(TaskListExcelBean::getId).collect(Collectors.toList());
            List<TaskListExcelBean> beanList = getNewRecordDetail(ids);
            Map<Long, TaskListExcelBean> map = beanList.stream().collect(Collectors.toMap(TaskListExcelBean::getId, r -> r));
            // 管控层级映射
            Set<Long> measureTypeIds = beanList.stream().filter(e -> e.getRiskMeasureTypeId() != null).map(TaskListExcelBean::getRiskMeasureTypeId).collect(Collectors.toSet());
            Map<Long, RiskMeasureTypeNode> allMeasureTypeMapping = CollectionUtil.isNotEmpty(measureTypeIds) ? riskMeasureTypeService.getAllTreeMapping(measureTypeIds) : new HashMap<>();
//            List<Long> getCheckUserIds = beanList.stream().filter(e->e.getCheckUserId() != null).map(TaskListExcelBean::getCheckUserId).collect(Collectors.toList());
//            List<BaseUser> users = userDao.getAllByIds(getCheckUserIds);
//            Map<Long, BaseUser> userMap = users.stream().collect(Collectors.toMap(BaseUser::getId, u -> u));

            for (TaskListExcelBean bean : list) {
                TaskListExcelVo vo = new TaskListExcelVo();
                BeanUtils.copyProperties(bean, vo);
                TaskListExcelBean taskListExcelBean = map.get(bean.getId());
                if (taskListExcelBean != null) {
                    vo.setRiskPointName(taskListExcelBean.getRiskPointName());
                    if (allMeasureTypeMapping.get(taskListExcelBean.getRiskMeasureTypeId()) != null) {
                        vo.setRiskMeasureTypeNodeName(allMeasureTypeMapping.get(taskListExcelBean.getRiskMeasureTypeId()).getMeasureTypeName());
                    }
                    if (!CollectionUtils.isEmpty(taskListExcelBean.getSimpleAssign())) {
                        vo.setCheckUserNames(taskListExcelBean.getSimpleAssign().get(0).getUserName());
                    }
                    vo.setHiddenDangerContent(taskListExcelBean.getHiddenDangerContent());
                    vo.setRiskMeasureContent(taskListExcelBean.getRiskMeasureContent());
                    vo.setRiskPointLevel(RiskLevels.findRiskNameByCode(Integer.parseInt(taskListExcelBean.getRiskPointLevel())));
                    vo.setCheckRateDescribe(taskListExcelBean.getCheckRateDescribe());
                    if (StringUtils.isBlank(vo.getVerifyState())) {
                        vo.setVerifyState("无需签到");
                    }
                    vos.add(vo);
                }
            }
            OutputStream planStatOut = response.getOutputStream();
            ExcelWriter planStatWriter = ExcelUtil.getWriter(true);
            buildV2RecordExcelHeader(planStatWriter);
            planStatWriter.write(vos, true);
            String planFileName = FileUtil.getEncodeFileName(request, "隐患排查记录");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", String.format("attachment;filename=%s", planFileName + ".xlsx"));
            planStatWriter.flush(planStatOut, true);
            planStatWriter.close();
            IoUtil.close(planStatOut);
        }
    }
    @Override
    public void newExportReport(TaskSearchBean search, HttpServletRequest request, HttpServletResponse
            response) throws IOException {
        setPageParam(search);
        List<TaskListExcelBean> list = getTaskRecords(search);
        List<TaskListExcelVo> vos = new ArrayList<>();
        List<OldTaskListExcelVo> oldListVo=new ArrayList<>();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)) {
            List<TaskListExcelBean> newList = list.stream().filter(bean -> bean.getSourceType() == 1).collect(Collectors.toList());
            List<TaskListExcelBean> oldList = list.stream().filter(bean -> bean.getSourceType() == 0).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(newList)) {
            List<Long> ids = newList.stream().map(TaskListExcelBean::getId).collect(Collectors.toList());
            List<TaskListExcelBean> beanList = getNewRecordDetail(ids);
            Map<Long, TaskListExcelBean> map = beanList.stream().collect(Collectors.toMap(TaskListExcelBean::getId, r -> r));
            // 管控层级映射
            Set<Long> measureTypeIds = beanList.stream().filter(e -> e.getRiskMeasureTypeId() != null).map(TaskListExcelBean::getRiskMeasureTypeId).collect(Collectors.toSet());
            Map<Long, RiskMeasureTypeNode> allMeasureTypeMapping = CollectionUtil.isNotEmpty(measureTypeIds) ? riskMeasureTypeService.getAllTreeMapping(measureTypeIds) : new HashMap<>();
            Map<Long, List<Long>> noCheckUserMap = new HashMap<>();

            for (TaskListExcelBean bean : newList) {
                if (bean != null && bean.getCheckUserId() != null && bean.getCheckUserId() == -1) {
                    List<Long> userIds = noCheckUserMap.get(bean.getId());
                    if (CollectionUtils.isEmpty(userIds)) {
                        userIds = taskMapper.findUserIds(bean.getId());
                    }
                    if (!CollectionUtils.isEmpty(userIds)) {
                        bean.setCheckUserId(CollectionUtils.isEmpty(userIds) ? -1 : userIds.get(0));
                        userIds.remove(0);
                        noCheckUserMap.put(bean.getId(), userIds);
                    }
                }
            }

            List<Long> checkUserIds = newList.stream().filter(each -> each.getCheckUserId() != null && each.getCheckUserId() != -1).map(TaskListExcelBean::getCheckUserId).collect(Collectors.toList());
            List<BaseUser> checkUsers = CollectionUtil.isEmpty(checkUserIds) ? new ArrayList<>() : userDao.getAllByIds(checkUserIds);
            Map<Long, BaseUser> checkUserMapping = checkUsers.stream().collect(Collectors.toMap(BaseUser::getId, r -> r));


            for (TaskListExcelBean bean : newList) {
                TaskListExcelVo vo = new TaskListExcelVo();
                BeanUtils.copyProperties(bean, vo);
                vo.setId(bean.getId() + "");
                TaskListExcelBean taskListExcelBean = map.get(bean.getId());
                if (taskListExcelBean != null) {
                    vo.setRiskPointName(taskListExcelBean.getRiskPointName());
                    if (allMeasureTypeMapping.get(taskListExcelBean.getRiskMeasureTypeId()) != null) {
                        vo.setRiskMeasureTypeNodeName(allMeasureTypeMapping.get(taskListExcelBean.getRiskMeasureTypeId()).getMeasureTypeName());
                    }
                    if (checkUserMapping.get(bean.getCheckUserId()) != null) {
                        vo.setCheckUserNames(checkUserMapping.get(bean.getCheckUserId()).getRealName());
                    }
                    vo.setHiddenDangerContent(taskListExcelBean.getHiddenDangerContent());
                    vo.setRiskMeasureContent(taskListExcelBean.getRiskMeasureContent());
                    vo.setRiskPointLevel(taskListExcelBean.getRiskPointLevel() == null ? "低风险" : RiskLevels.findRiskNameByCode(Integer.parseInt(taskListExcelBean.getRiskPointLevel())));
                    vo.setCheckRateDescribe(taskListExcelBean.getCheckRateDescribe());
                    if (StringUtils.isBlank(vo.getVerifyState())) {
                        vo.setVerifyState("无需签到");
                    }
                    vos.add(vo);
                }
            }
        }
            if (!CollectionUtils.isEmpty(oldList)) {
                List<BpInvestigateRecordBean> oldResult = getOldPlanRecords(oldList);
                oldListVo = getOldTaskListExcelVo(oldResult);
            }
            OutputStream planStatOut = response.getOutputStream();
            ExcelWriter planStatWriter = ExcelUtil.getWriterWithSheet("隐患排查记录");
            buildV2RecordExcelHeader(planStatWriter);
            planStatWriter.write(vos, true);

            buildV2OldRecordExcelHeader(planStatWriter);
            planStatWriter.write(oldListVo, true);

            String planFileName = FileUtil.getEncodeFileName(request, "隐患排查记录");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", String.format("attachment;filename=%s", planFileName + ".xlsx"));
            planStatWriter.flush(planStatOut, true);
            planStatWriter.close();
            IoUtil.close(planStatOut);
        }
    }

    public List<OldTaskListExcelVo> getOldTaskListExcelVo(List<BpInvestigateRecordBean> beans){
        List<OldTaskListExcelVo> vos=new ArrayList<>();
        for (BpInvestigateRecordBean bean : beans) {
            for (BpInvestigateRecordItemBean itemBean : bean.getItemBeanList()) {
                OldTaskListExcelVo vo = new OldTaskListExcelVo();
                BeanUtils.copyProperties(itemBean,vo);
                BeanUtils.copyProperties(bean,vo);
                if (bean.getPlanBean()!=null) {
                    vo.setCheckPlanName(bean.getPlanBean().getCheckPlanName());
                    vo.setRiskMeasureTypeNodeName(bean.getPlanBean().getCheckWay());
                    vo.setTypeName(bean.getPlanBean().getTypeName());
                }
                vo.setAttachmentList("暂不支持照片导出");
                vo.setAutograph("暂不支持");
                vo.setDutyDepartName(bean.getDutyDepartName());
                // 处理数字太长导出变成科学计数法
                if (vo.getId() != null) {
                    BigDecimal bId = new BigDecimal(vo.getId());
                    vo.setCheckId(bId.toPlainString());
                }
                vos.add(vo);
            }
        }
        return vos;
    }

    public List<BpInvestigateRecordBean> getOldPlanRecords(List<TaskListExcelBean> oldList){
        List<BpInvestigateRecordBean> recordBeans = new ArrayList<>();
        List<Long> taskIds = oldList.stream().map(TaskListExcelBean::getId).collect(Collectors.toList());
        List<Long> trueIds=new ArrayList<>();
        List<Long> falseIds=new ArrayList<>();
        List<BpInvestigateRecord> records=new ArrayList<>();
        List<BpInvestigateRecord> hisRecords=new ArrayList<>();

        Map<String, List<Long>> map = getTaskIds(taskIds);
        trueIds = map.get("trueIds");
        falseIds = map.get("falseIds");
        // 兼容历史页面和今日页面
        if (!CollectionUtils.isEmpty(falseIds)) {
          records = recordDao.findAllByTaskIdIn(falseIds);
        }
        if (!CollectionUtils.isEmpty(trueIds)) {
            hisRecords = historyMapper.getRecordByTaskIds(trueIds);
        }
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(records)) {
            List<Long> planIds = records.stream().map(BpInvestigateRecord::getCheckPlanId).collect(Collectors.toList());
//            List<Long> userIds = records.stream().map(BpInvestigateRecord::getCheckUserId).collect(Collectors.toList());
            List<Long> ids = records.stream().map(BpInvestigateRecord::getId).collect(Collectors.toList());
            List<BpInvestigatePlanBean> planBeans = planService.findBeanByIds(planIds);
//            planBeans.stream().collect(Collectors.groupingBy(BpInvestigatePlanBean::getPlanDate));
            Map<Long, BpInvestigatePlanBean> planBeanMap = planBeans.stream().collect(Collectors.toMap(BpInvestigatePlanBean::getId, r -> r));
            List<BpInvestigateRecordItem> itemList = recordItemDao.findByRecordIdIn(ids);
            Map<Long, List<BpInvestigateRecordItem>> recordItemMap = itemList.stream().collect(Collectors.groupingBy(BpInvestigateRecordItem::getRecordId));
            Map<Long,List<Long>> noCheckUserMap=new HashMap<>();
            for (BpInvestigateRecord bean : records) {

                if (bean!=null&&bean.getCheckUserId()!=null&&bean.getCheckUserId()==-1){
                    List<Long> userIds = noCheckUserMap.get(bean.getId());
                    if (CollectionUtils.isEmpty(userIds)) {
                        userIds  = taskMapper.findUserIds(bean.getId());
                    }
                    if (!CollectionUtils.isEmpty(userIds)) {
                        bean.setCheckUserId(CollectionUtils.isEmpty(userIds)?-1:userIds.get(0));
                        userIds.remove(0);
                        noCheckUserMap.put(bean.getId(),userIds);
                    }
                }
            }

            List<Long> checkUserIds = oldList.stream().filter(each -> each.getCheckUserId() != null && each.getCheckUserId() != -1).map(TaskListExcelBean::getCheckUserId).collect(Collectors.toList());
            List<BaseUser> checkUsers = CollectionUtil.isEmpty(checkUserIds) ? new ArrayList<>() : userDao.getAllByIds(checkUserIds);
            Map<Long, BaseUser> checkUserMapping = checkUsers.stream().collect(Collectors.toMap(BaseUser::getId, r -> r));
            List<Long> deptIds = records.stream().map(BpInvestigateRecord::getDutyDepartId).collect(Collectors.toList());
            Map<Long, BpDepart> departMap = bpDepartService.getDepartMapByIds(deptIds);
            for (BpInvestigateRecord record : records) {
                BpInvestigateRecordBean recordBean = new BpInvestigateRecordBean();
                BeanUtils.copyProperties(record, recordBean);
                recordBean.setPlanBean(planBeanMap.get(record.getCheckPlanId()));
                if (checkUserMapping.get(record.getCheckUserId())!=null) {
                    recordBean.setCheckUserName(checkUserMapping.get(record.getCheckUserId()).getRealName());
                }
                if (departMap.get(record.getDutyDepartId())!=null) {
                    recordBean.setDutyDepartName(departMap.get(record.getDutyDepartId()).getName());
                }
                //检查项目
                List<BpInvestigateRecordItem> bpInvestigateRecordItems = recordItemMap.get(record.getId());
                if (CollectionUtil.isEmpty(bpInvestigateRecordItems)) {
                    bpInvestigateRecordItems = bpInvestigateTaskHisMapper.getHistoryItemByRecordId(record.getId());
                    List<Long> itemIdList = bpInvestigateRecordItems.stream().map(r -> r.getCheckItemId()).distinct().collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(bpInvestigateRecordItems)) {
                        Map<Long, BpSafeTableItem> tableItemMap = tableItemDao.findAllById(itemIdList).stream().collect(Collectors.toMap(r -> r.getId(), r -> r));
                        List<BpInvestigateRecordItemBean> itemBeanList = getBpInvestigateRecordItemBeans(bpInvestigateRecordItems, tableItemMap);
                        recordBean.setItemBeanList(itemBeanList);
                        recordBeans.add(recordBean);
                    }
                }

            }
        }

        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(hisRecords)) {
            List<Long> planIds = hisRecords.stream().map(BpInvestigateRecord::getCheckPlanId).collect(Collectors.toList());
            List<Long> ids = hisRecords.stream().map(BpInvestigateRecord::getId).collect(Collectors.toList());
            List<BpInvestigatePlanBean> planBeans = planService.findBeanByIds(planIds);
            Map<Long, BpInvestigatePlanBean> planBeanMap = planBeans.stream().collect(Collectors.toMap(BpInvestigatePlanBean::getId, r -> r));
            List<BpInvestigateRecordItem> itemList = recordItemDao.findByRecordIdIn(ids);
            Map<Long, List<BpInvestigateRecordItem>> recordItemMap = itemList.stream().collect(Collectors.groupingBy(BpInvestigateRecordItem::getRecordId));
            Map<Long,List<Long>> noCheckUserMap=new HashMap<>();
            for (BpInvestigateRecord bean : hisRecords) {

                if (bean!=null&&bean.getCheckUserId()!=null&&bean.getCheckUserId()==-1){
                    List<Long> userIds = noCheckUserMap.get(bean.getId());
                    if (CollectionUtils.isEmpty(userIds)) {
                        userIds  = taskMapper.findUserIds(bean.getId());
                    }
                    if (!CollectionUtils.isEmpty(userIds)) {
                        bean.setCheckUserId(CollectionUtils.isEmpty(userIds)?-1:userIds.get(0));
                        userIds.remove(0);
                        noCheckUserMap.put(bean.getId(),userIds);
                    }
                }
            }

            List<Long> checkUserIds = oldList.stream().filter(each -> each.getCheckUserId() != null && each.getCheckUserId() != -1).map(TaskListExcelBean::getCheckUserId).collect(Collectors.toList());
            List<BaseUser> checkUsers = CollectionUtil.isEmpty(checkUserIds) ? new ArrayList<>() : userDao.getAllByIds(checkUserIds);
            Map<Long, BaseUser> checkUserMapping = checkUsers.stream().collect(Collectors.toMap(BaseUser::getId, r -> r));
            List<Long> deptIds = hisRecords.stream().map(BpInvestigateRecord::getDutyDepartId).collect(Collectors.toList());
            Map<Long, BpDepart> departMap = bpDepartService.getDepartMapByIds(deptIds);
            for (BpInvestigateRecord record : hisRecords) {
                BpInvestigateRecordBean recordBean = new BpInvestigateRecordBean();
                BeanUtils.copyProperties(record, recordBean);
                recordBean.setPlanBean(planBeanMap.get(record.getCheckPlanId()));
                if (checkUserMapping.get(record.getCheckUserId())!=null) {
                    recordBean.setCheckUserName(checkUserMapping.get(record.getCheckUserId()).getRealName());
                }
                if (departMap.get(record.getDutyDepartId())!=null) {
                    recordBean.setDutyDepartName(departMap.get(record.getDutyDepartId()).getName());
                }
                //检查项目
                List<BpInvestigateRecordItem> bpInvestigateRecordItems = recordItemMap.get(record.getId());
                if (CollectionUtil.isEmpty(bpInvestigateRecordItems)) {
                    bpInvestigateRecordItems = bpInvestigateTaskHisMapper.getHistoryItemByRecordId(record.getId());
                    List<Long> itemIdList = bpInvestigateRecordItems.stream().map(r -> r.getCheckItemId()).distinct().collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(bpInvestigateRecordItems)) {
                        Map<Long, BpSafeTableItem> tableItemMap = tableItemDao.findAllById(itemIdList).stream().collect(Collectors.toMap(r -> r.getId(), r -> r));
                        List<BpInvestigateRecordItemBean> itemBeanList = getBpInvestigateRecordItemBeans(bpInvestigateRecordItems, tableItemMap);
                        recordBean.setItemBeanList(itemBeanList);
                        recordBeans.add(recordBean);
                    }
                }

            }
        }

        return recordBeans;
    }


    private List<BpInvestigateRecordItemBean> getBpInvestigateRecordItemBeans
            (List<BpInvestigateRecordItem> itemList, Map<Long, BpSafeTableItem> tableItemMap) {
        List<BpInvestigateRecordItemBean> itemBeanList = Lists.newArrayList();
        for (BpInvestigateRecordItem recordItem : itemList) {
            BpInvestigateRecordItemBean itemBean = new BpInvestigateRecordItemBean();
            BeanUtils.copyProperties(recordItem, itemBean);
            BpSafeTableItem tableItem = tableItemMap.get(itemBean.getCheckItemId());
            if (tableItem != null) {
                itemBean.setItem(tableItem.getItem());
                itemBean.setContent(tableItem.getContent());
                itemBean.setStandard(tableItem.getStandard());
            }
            String json = recordItem.getAttachmentJson();
            if (!StringUtils.isEmpty(json)) {
                //兼容APP保存的图片，去除空的图片
                List<BaseAttachmentBean> baseAttachmentBeans = JSON.parseArray(json, BaseAttachmentBean.class).stream().filter(e -> e.getId() != null).collect(Collectors.toList());
                itemBean.setAttachmentList(baseAttachmentBeans);
            }
            itemBeanList.add(itemBean);
            String wfProcessInsId = recordItem.getWfProcessInsId();
            if (StringUtils.isNotBlank(wfProcessInsId)) {
                itemBean.setWorkFlowStatus(recordItem.getWfProcessStatus());
            }
        }
        return itemBeanList;
    }
    @Override
    public void exportStatisticsList(TaskSearchBean search, HttpServletRequest request, HttpServletResponse
            response) throws IOException {
        setPageParam(search);
        Page<TaskStatiUserVo> statisticsPage = getStatistics(search);

        List<TaskStatiUserVo> records = statisticsPage.getRecords();

        List<TaskStatiUserExcelVo> excelRecords = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(records)) {
            // 序号
            for (int i = 0; i < records.size(); i++) {
                TaskStatiUserExcelVo vo = new TaskStatiUserExcelVo();
                records.get(i).setOrderNo(i + 1);
                BeanUtils.copyProperties(records.get(i), vo);
                excelRecords.add(vo);
            }
        }
        OutputStream statListOut = response.getOutputStream();
        ExcelWriter statListWriter = ExcelUtil.getWriter(true);
        buildStatisticsListHeader(statListWriter);
        statListWriter.write(excelRecords, true);
        String fileName = FileUtil.getEncodeFileName(request, "隐患排查统计");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", String.format("attachment;filename=%s", fileName + ".xlsx"));
        statListWriter.flush(statListOut, true);
        statListWriter.close();
        IoUtil.close(statListOut);
    }

    private void setPageParam(TaskSearchBean search) {
        if (search.getSize() == null) {
            search.setSize(20000);
        }
        if (search.getPage() == null) {
            search.setPage(0);
        }
    }

    private void buildRecordExcelHeader(ExcelWriter writer) {
        writer.addHeaderAlias("id", "排查单编号");
        writer.addHeaderAlias("checkName", "排查名称");
        writer.addHeaderAlias("checkType", "排查类型");
        writer.addHeaderAlias("startTime", "任务计划时间");
        writer.addHeaderAlias("finishTime", "完成时间");
        writer.addHeaderAlias("checkUserNames", "排查人员");
        writer.addHeaderAlias("checkResult", "排查结果");
        writer.addHeaderAlias("exceptStatus", "异常处理");
    }

    private void buildV2RecordExcelHeader(ExcelWriter writer) {
        writer.addHeaderAlias("id", "排查单编号");
        writer.addHeaderAlias("riskPointName", "分析单元");
        writer.addHeaderAlias("riskPointLevel", "风险等级");
        writer.addHeaderAlias("riskMeasureTypeNodeName", "管控措施类型");
        writer.addHeaderAlias("riskMeasureContent", "管控措施");
        writer.addHeaderAlias("hiddenDangerContent", "隐患排查内容");
        writer.addHeaderAlias("checkRateDescribe", "排查周期");
        writer.addHeaderAlias("startTime", "任务计划时间");
        writer.addHeaderAlias("finishTime", "排查完成时间");
        writer.addHeaderAlias("checkUserNames", "隐患排查人员");
        writer.addHeaderAlias("verifyState", "签到情况");
        writer.addHeaderAlias("checkResult", "排查结果");
        writer.addHeaderAlias("problemDescription", "问题描述");
    }


    private void buildV2OldRecordExcelHeader(ExcelWriter writer) {
        writer.setSheet("计划性隐患排查记录");
        writer.addHeaderAlias("checkId", "排查单编号");
        writer.addHeaderAlias("checkPlanName", "排查计划");
        writer.addHeaderAlias("typeName", "排查类型");
        writer.addHeaderAlias("riskMeasureTypeNodeName", "排查方式");
        writer.addHeaderAlias("checkUserName", "排查人员");
        writer.addHeaderAlias("dutyDepartName", "受检单位");
        writer.addHeaderAlias("checkFinishDate", "排查完成日期");
        writer.addHeaderAlias("remark", "备注");
//        writer.addHeaderAlias("participants", "参与人员");
        writer.addHeaderAlias("item", "排查项目");
        writer.addHeaderAlias("content", "排查内容");
        writer.addHeaderAlias("standard", "排查依据");
        writer.addHeaderAlias("problemDescription", "问题描述");
        writer.addHeaderAlias("attachmentList", "上传照片");
        writer.addHeaderAlias("repairStatus", "状态");
        writer.addHeaderAlias("autograph", "电子签名");
    }


    private void buildStatisticsListHeader(ExcelWriter writer) {
        writer.addHeaderAlias("orderNo", "序号");
        writer.addHeaderAlias("userName", "排查人员");
        writer.addHeaderAlias("departName", "所在部门");
        writer.addHeaderAlias("totalTask", "排查总任务数");
//        writer.addHeaderAlias("noCheckTask", "待排查的任务数");
        writer.addHeaderAlias("finishTask", "正常完成任务数");
        writer.addHeaderAlias("unCheckTask", "未检漏检任务数");
        writer.addHeaderAlias("timeOutFinish", "逾期完成任务数");
        writer.addHeaderAlias("totalHidden", "发现隐患数量");
    }

    @Override
    @Scheduled(cron = "0 30 1 * * ?")
    @Transactional
    public synchronized void moveData() {
        int keepDay = 1;
        BaseConfig config = configService.findFirstConfig(BaseConfigCodes.INVESTIGATE_DATA_KEEP);
        if (null != config) {
            try {
                // keepDay 不能配置为小于 1
                keepDay = Integer.parseInt(config.getValue());
                keepDay = Math.max(keepDay, 1);
            }catch (Exception e) {
                log.info("{}配置错误：{}", BaseConfigCodes.INVESTIGATE_DATA_KEEP, config.getValue());
            }
        }
        DateTime border = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -1 * (keepDay - 1));
        // moveTask
        moveTask(border);
        // moveSummary
        taskSummaryService.moveSummary(border);
    }

    @Override
    @Transactional
    public void moveDataHand(Date border) {
        // moveTask
        moveTask(border);
        // moveSummary
        taskSummaryService.moveSummary(border);
    }

    @Override
    public Page<TaskVo> findTaskList(TaskSearchVo search) {
        if (CollectionUtil.isEmpty(search.getPlanIds())){
            return new Page<>();
        }
        search.setOrgCode(Context.getCompanyCode());
        search.setTenentId(Context.getCurrentTenantId());
        if (StringUtils.isNotBlank(search.getCheckUserName())) {
            List<Long> userIds = userDao.findByNameLikeIgnoreDeleteStatus(search.getCheckUserName());
            // 按人员搜索，查无此人
            if (CollectionUtil.isEmpty(userIds)) {
                return new Page<>();
            }
            search.setCheckUserIds(userIds);
        }
        Page<BpInvestigateTask> page = new Page<>(search.getPage() + 1, search.getSize());
        Page<TaskVo> taskPage = taskMapper.findTaskListPage(page, search);
        for (TaskVo vo : taskPage.getRecords()){
            vo.setCheckUserName(userDao.getBaseUserNameById(vo.getExecutorId()));
            if (vo.getJobId() != null){
                vo.setJobName(jobDao.getNameById(vo.getJobId()));
            }
            if (StringUtils.isNotBlank(vo.getCheckJobJson())){
                List<Long> jobIds = JsonUtil.fromListJson(vo.getCheckJobJson(), Long.class);
                List<String> jobNameList = jobDao.findAllByIdInfo(jobIds).stream().map(BpJob::getName).collect(Collectors.toList());
                vo.setJobName(String.join(",",jobNameList));
            }
        }
        return taskPage;
    }

    @Override
    @Transactional
    public void deleteBatch(TaskDelDTO bean) {
        if (bean.getDelAllFlag()){
            //删除全部，根据计划ID
            List<Long> taskIds = taskMapper.findByPlanIds(bean.getIds());
            if (CollectionUtil.isEmpty(taskIds)){
                return;
            }
            //先删除assign SummaryId为空直接删除
            taskMapper.deleteAssignByTaskIds(taskIds);

            List<BpInvestigateTaskAssign> assigns = taskMapper.findAssigns(taskIds);
            if (CollectionUtil.isNotEmpty(assigns)){
                //拆分
                Map<Long,List<BpInvestigateTaskAssign>> map = assigns.stream().collect(Collectors.groupingBy(BpInvestigateTaskAssign::getSummaryId));
                //更新统计表
                for (Long summaryId : map.keySet()){
                    List<BpInvestigateTaskAssign> assignList = map.get(summaryId);
                    taskMapper.updateTaskCount(summaryId,assignList.size());
                    bpInvestigateTaskAssignService.deleteByIds(assignList.stream().map(BpInvestigateTaskAssign::getId).collect(Collectors.toList()));
                }
            }
            //删除task
            taskMapper.deleteTaskByIds(taskIds);
            return;
        }
        List<BpInvestigateTaskAssign> assigns = taskMapper.findAssignsById(bean.getIds());
        for (BpInvestigateTaskAssign assign : assigns){
            if (assign.getSummaryId() != null){
                taskMapper.updateTaskCount(assign.getSummaryId(),1);
            }
        }
        List<Long> taskIds = assigns.stream().map(BpInvestigateTaskAssign::getTaskId).collect(Collectors.toList());
        bpInvestigateTaskAssignService.deleteByIds(assigns.stream().map(BpInvestigateTaskAssign::getId).collect(Collectors.toList()));
        List<Long> taskDelIds = Lists.newArrayList();
        for (Long taskId : taskIds){
            Integer assignsCount = bpInvestigateTaskAssignService.findAssignsCount(taskId);
            if (assignsCount == 0){
                taskDelIds.add(taskId);
            }
        }
        if (!CollectionUtils.isEmpty(taskDelIds)) {
            taskMapper.deleteTaskByIds(taskDelIds);
        }
    }

    @Override
    public BpInvestigateTask findOne(Long planId, Date checkDate, Date deadline) {
        return taskMapper.findOne(planId,checkDate,deadline);
    }

    @Override
    public String deleteTask(TaskDelBean bean) {
        List<Long> taskIds = Lists.newArrayList();
        //删除所有【已生成】但【未排查】的任务
        if (bean.getDeleted() == 1){
            taskIds = taskMapper.findTasks(null);
        }else {
            if (bean.getTime() != null){
                taskIds = taskMapper.findTasks(bean.getTime());
            }
        }
        if (CollectionUtil.isEmpty(taskIds)){
            return "无可删除任务";
        }
        //先删除assign SummaryId为空直接删除
        long taskCount;
        taskCount = taskMapper.deleteAssignByTaskIds(taskIds);

        List<BpInvestigateTaskAssign> assigns = taskMapper.findAssigns(taskIds);
        if (CollectionUtil.isNotEmpty(assigns)){
            //拆分
            Map<Long,List<BpInvestigateTaskAssign>> map = assigns.stream().collect(Collectors.groupingBy(BpInvestigateTaskAssign::getSummaryId));
            //更新统计表
            for (Long summaryId : map.keySet()){
                List<BpInvestigateTaskAssign> assignList = map.get(summaryId);
                taskMapper.updateTaskCount(summaryId,assignList.size());
                taskCount += taskMapper.deleteAssignByIds(assignList.stream().map(BpInvestigateTaskAssign::getId).collect(Collectors.toList()));
            }
        }
        //删除task
        taskMapper.deleteTaskByIds(taskIds);
        return "删除任务成功"+taskCount+"条！";
    }

    @Override
    public List<BpInvestigateTask> findTodayTask(Long planId) {
        return taskMapper.findTodayTask(planId);
    }

    @Override
    public List<AppCheckTaskVo.PointTaskGroup> selectByDistrictId(Long districtId,Long userId) {
        List<AppCheckTaskVo.PointTaskGroup> list=new ArrayList<>();
        List<Long> taskIds = taskMapper.selectByDistrictId(districtId, userId);
        if (!CollectionUtils.isEmpty(taskIds)) {
          list = taskSummaryService.getTaskIdsById(taskIds);
        }

        return list;
    }

    /**
     * 迁移task数据
     * @param border
     * @return
     */
    private void moveTask(Date border) {
        List<Long> taskIds = taskMapper.getIdByDate(border);
        if (CollectionUtil.isNotEmpty(taskIds)) {
            long startTimeTotal = System.currentTimeMillis();
            List<List<Long>> taskList = Lists.partition(taskIds,100);
            int index = 1;
            for (List<Long> ids : taskList){
                try {
                    long startTime = System.currentTimeMillis();
                    taskSummaryService.moveTaskSub(ids);
                    log.info(String.format("第%d批迁移%d个任务共耗时%dms", index, ids.size(), System.currentTimeMillis() - startTime));
                    index++;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            log.info(String.format("迁移%d个任务总共耗时%dms", taskIds.size(), System.currentTimeMillis() - startTimeTotal));
        }
    }

    /**
     * 每天凌晨2点~3点, 每两分钟执行一次, 迁移增量的his数据
     */
    @Scheduled(cron = "0 0/2 02-03 * * ?")
    @Transactional
    @Override
    public void moveHisDataDaily() {
        if (redisClient.get(Constant.MOVE_INVESTIGATE_HIS_OVER_FLAG) == null) {
            return;
        }
        boolean open = false;
        BaseConfig config = configService.findConfig(1L, "001-001", BaseConfigCodes.INVESTIGATE_HIS_DATA_MOVE);
        if (null != config) {
            try {
                open = "1".equals(config.getValue());
            } catch (Exception e) {
                log.info("{} 配置错误：{}", BaseConfigCodes.INVESTIGATE_HIS_DATA_MOVE, config.getValue());
            }
        }
        if (open) {
            BaseConfig hisDataSaveMonthConfig = configService.findConfig(1L, "001-001", BaseConfigCodes.INVESTIGATE_HIS_DATA_SAVE_MONTH);
            if (hisDataSaveMonthConfig == null || StringUtil.isEmpty(hisDataSaveMonthConfig.getValue())) {
                log.warn("========= 隐患排查his表数据保留月数配置为空!");
                return;
            }
            int saveMonth = Integer.parseInt(hisDataSaveMonthConfig.getValue());
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("每日一次迁移hisTask相关数据");
            // 查询近saveMonth个月之外的数据
            Date endDate = DateUtil.offsetMonth(DateUtil.beginOfDay(new Date()), -saveMonth);
            // hisTask相关数据迁移
            int taskNum = moveHisTask(endDate, 1);
            stopWatch.stop();
            log.info("========= {}, taskNum: {}, 耗时: {} ms", stopWatch.getLastTaskName(), taskNum, stopWatch.getLastTaskTimeMillis());

            stopWatch.start("每日一次迁移hiSummary相关数据");
            // hisSummary数据迁移
            int summaryNum = moveHisSummary(endDate, false);
            stopWatch.stop();
            log.info("========= {}, summaryNum: {}, 耗时: {} ms", stopWatch.getLastTaskName(), summaryNum, stopWatch.getLastTaskTimeMillis());
            log.info("========= 每日一次迁移隐患排查数据, his保留时长: {} 个月, taskNum: {}, summaryNum, {}, 总耗时: {} ms", saveMonth, taskNum, summaryNum, stopWatch.getTotalTimeMillis());
        }
    }

    /**
     * 上线后, 每8秒执行一次, 迁移存量的his数据, 迁移结束此job便不再执行
     */
    @Scheduled(cron = "0/8 * * * * ?")
    @Transactional
    @Override
    public void moveHisData() {
        if (redisClient.get(Constant.MOVE_INVESTIGATE_HIS_OVER_FLAG) != null) {
            return;
        }
        boolean open = false;
        BaseConfig config = configService.findConfig(1L, "001-001", BaseConfigCodes.INVESTIGATE_HIS_DATA_MOVE);
        if (null != config) {
            try {
                open = "1".equals(config.getValue());
            } catch (Exception e) {
                log.info("{} 配置错误：{}", BaseConfigCodes.INVESTIGATE_HIS_DATA_MOVE, config.getValue());
            }
        }
        if (open) {
            BaseConfig hisDataSaveMonthConfig = configService.findConfig(1L, "001-001", BaseConfigCodes.INVESTIGATE_HIS_DATA_SAVE_MONTH);
            if (hisDataSaveMonthConfig == null || StringUtil.isEmpty(hisDataSaveMonthConfig.getValue())) {
                log.warn("========= 隐患排查his表数据保留月数配置为空!");
                return;
            }
            int saveMonth = Integer.parseInt(hisDataSaveMonthConfig.getValue());
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("迁移hisTask相关数据");
            // 查询近saveMonth个月之外的数据
            Date endDate = DateUtil.offsetMonth(DateUtil.beginOfDay(new Date()), -saveMonth);
            // hisTask相关数据迁移
            int taskNum = moveHisTask(endDate, 2);
            stopWatch.stop();
            log.info("========= {}, taskNum: {}, 耗时: {} ms", stopWatch.getLastTaskName(), taskNum, stopWatch.getLastTaskTimeMillis());

            stopWatch.start("迁移hisSummary相关数据");
            // hisSummary数据迁移
            int summaryNum = moveHisSummary(endDate, true);
            stopWatch.stop();
            log.info("========= {}, summaryNum: {}, 耗时: {} ms", stopWatch.getLastTaskName(), summaryNum, stopWatch.getLastTaskTimeMillis());
            if (taskNum == 0 && summaryNum == 0) {
                log.info("========== 存量隐患排查his数据已迁移完毕!");
                redisClient.set(Constant.MOVE_INVESTIGATE_HIS_OVER_FLAG, "1");
            }
            log.info("========= 迁移隐患排查his数据, his保留时长: {} 个月, taskNum: {}, summaryNum: {}, 总耗时: {} ms", saveMonth, taskNum, summaryNum, stopWatch.getTotalTimeMillis());
        }
    }

    /**
     * @param endDate 查询截止日期
     * @param type    1-每日一次的增量数据任务 2-一次性跑存量数据任务
     */
    private int moveHisTask(Date endDate, int type) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy");
        // 处理taskHis相关数据, 每次查询1000条进行处理
        List<BpInvestigateTaskHis> hisTasks = taskHisMapper.getMoveTaskIds(endDate, type);
        if (CollectionUtil.isEmpty(hisTasks)) {
            return 0;
        }
        Map<String, List<BpInvestigateTaskHis>> hisTaskMap = hisTasks.stream().collect(Collectors.groupingBy(item -> sdf1.format(item.getCreateTime())));
        hisTaskMap.forEach((key, value) -> {
            List<Long> ids = value.stream().map(BpInvestigateTaskHis::getId).collect(Collectors.toList());
            List<List<Long>> idsList = Lists.partition(ids, 100);
            int index = 1;
            StopWatch stopWatch = new StopWatch();
            for (List<Long> singleIds : idsList) {
                try {
                    stopWatch.start(String.format("第%s批迁移hisTask数据, 共计%s条", index, singleIds != null ? singleIds.size() : 0));
                    taskSummaryService.doMoveHisTaskSub(singleIds, key);
                    index++;
                    stopWatch.stop();
                    log.info("========= {}, 耗时: {} ms", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        return hisTasks.size();
    }

    private int moveHisSummary(Date endDate, boolean limit) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy");
        // 处理summaryHis相关数据, 每次查询1000条进行处理
        List<BpInvestigateTaskSummaryHis> summaryHisList = taskSummaryHisMapper.getMoveSummaryIds(endDate, limit);
        if (CollectionUtil.isEmpty(summaryHisList)) {
            return 0;
        }
        Map<String, List<BpInvestigateTaskSummaryHis>> summaryHisMap = summaryHisList.stream().collect(Collectors.groupingBy(item -> sdf1.format(item.getCreateTime())));
        summaryHisMap.forEach((key, value) -> {
            List<Long> ids = value.stream().map(BpInvestigateTaskSummaryHis::getId).collect(Collectors.toList());
            List<List<Long>> idsList = Lists.partition(ids, 100);
            int index = 1;
            StopWatch stopWatch = new StopWatch();
            for (List<Long> singleIds : idsList) {
                try {
                    stopWatch.start(String.format("第%s批迁移hisSummary数据, 共计%s条", index, singleIds != null ? singleIds.size() : 0));
                    taskSummaryService.doMoveHisSummary(singleIds, key);
                    index++;
                    stopWatch.stop();
                    log.info("========= {}, 耗时: {} ms", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        return summaryHisList.size();
    }

}
